package com.redepronik.negosyscom.invfac.controller;

import static com.redepronik.negosys.utils.Utils.fechaFormatoDate;
import static com.redepronik.negosys.utils.Utils.iva;
import static com.redepronik.negosys.utils.Utils.newBigDecimal;
import static com.redepronik.negosys.utils.Utils.parametro;
import static com.redepronik.negosys.utils.Utils.redondear;
import static com.redepronik.negosys.utils.Utils.timestamp;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.primefaces.context.RequestContext;
import org.primefaces.event.CellEditEvent;
import org.primefaces.event.SelectEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;

import com.redepronik.negosys.invfac.entity.Bodega;
import com.redepronik.negosys.invfac.entity.Detalleegreso;
import com.redepronik.negosys.invfac.entity.Egreso;
import com.redepronik.negosys.invfac.entity.Entrada;
import com.redepronik.negosys.invfac.entity.Guiaremision;
import com.redepronik.negosys.invfac.entity.Kardex;
import com.redepronik.negosys.invfac.entity.Local;
import com.redepronik.negosys.invfac.entity.Motivotraslado;
import com.redepronik.negosys.invfac.entity.Pagoentrada;
import com.redepronik.negosys.invfac.entity.Producto;
import com.redepronik.negosys.invfac.entity.Tipopago;
import com.redepronik.negosys.invfac.entityAux.CantidadFactura;
import com.redepronik.negosys.invfac.entityAux.EntradaReporte;
import com.redepronik.negosys.invfac.entityAux.FacturaReporte;
import com.redepronik.negosys.invfac.entityAux.PersonaCedulaNombre;
import com.redepronik.negosys.invfac.service.EgresoService;
import com.redepronik.negosys.invfac.service.GuiaRemisionService;
import com.redepronik.negosys.invfac.service.KardexService;
import com.redepronik.negosys.invfac.service.LocalService;
import com.redepronik.negosys.invfac.service.MotivoTrasladoService;
import com.redepronik.negosys.invfac.service.ProductoService;
import com.redepronik.negosys.invfac.service.TipoDocumentoService;
import com.redepronik.negosys.invfac.service.TipoPagoService;
import com.redepronik.negosys.rrhh.entity.Empleadocargo;
import com.redepronik.negosys.rrhh.entity.Persona;
import com.redepronik.negosys.rrhh.service.ClienteService;
import com.redepronik.negosys.rrhh.service.EmpleadoService;
import com.redepronik.negosys.rrhh.service.PersonaService;
import com.redepronik.negosyscom.invfac.report.EgresoReport;

@Controller
@Scope("session")
public class FacturaBean implements Serializable {

	private static final long serialVersionUID = 1L;

	@Autowired
	private MotivoTrasladoService motivoTrasladoService;

	@Autowired
	private EgresoService egresoService;

	@Autowired
	private ProductoService productoService;

	@Autowired
	private KardexService kardexService;

	@Autowired
	private ClienteService clienteService;

	@Autowired
	private LocalService localService;

	@Autowired
	private GuiaRemisionService guiaRemisionService;

	@Autowired
	private TipoDocumentoService tipoDocumentoService;

	@Autowired
	private TipoPagoService tipoPagoService;

	@Autowired
	private PersonaService personaService;

	@Autowired
	private EgresoReport egresoReport;

	@Autowired
	private EmpleadoService empleadoService;

	private List<Tipopago> listTiposPago;
	private List<EntradaReporte> listaEntradaReporte;
	private List<Local> listaLocales;
	private List<Motivotraslado> listaMotivotraslados;
	private List<PersonaCedulaNombre> listaVendedores;
	private List<PersonaCedulaNombre> listaTransportistas;

	private Egreso egreso;
	private Persona cliente;
	private Empleadocargo vendedor;
	private Entrada entrada;
	private Pagoentrada pagosEntrada;
	private Tipopago tiposPago;
	private Date fechaInicio;
	private Empleadocargo transportista;

	private Guiaremision guiaRemision;
	private boolean guia;

	private Producto producto;

	private List<FacturaReporte> facturaReportes;
	private FacturaReporte facturaReporte;
	private CantidadFactura cantidadFacturaCalculos;
	private CantidadFactura cantidadFacturaPresentar;
	private BigDecimal restante;
	private BigDecimal restanteAux;
	private BigDecimal cambio;
	private BigDecimal totalMonto;

	private Integer cantidad;
	private BigDecimal nuevoPrecio;

	private Bodega bodega;
	private Integer fila;
	private boolean bnLocal;

	private boolean bnBanco;
	private boolean bnEfectivo;
	private boolean bnTarjeta;

	private String chequeTarjetaVaucher;
	private String chequeTarjetaCuenta;

	// Cuadro de Busqueda de productos
	private List<Producto> listaProductoBusqueda;
	private String criterioProductoBusqueda;

	// Cuadro de Busqueda de clientes
	private List<Persona> listaClienteBusqueda;
	private String criterioClienteBusqueda;

	private boolean bn = true;

	public FacturaBean() {
		listTiposPago = new ArrayList<Tipopago>();
		listaEntradaReporte = new ArrayList<EntradaReporte>();

		cliente = new Persona();
		entrada = new Entrada();
		pagosEntrada = new Pagoentrada();
		tiposPago = new Tipopago();
		fechaInicio = new Date();
		producto = new Producto();
		facturaReportes = new ArrayList<FacturaReporte>();
		facturaReporte = new FacturaReporte();
		cantidadFacturaCalculos = new CantidadFactura();
		cantidadFacturaPresentar = new CantidadFactura();
		restante = newBigDecimal();
		cambio = newBigDecimal();
		totalMonto = new BigDecimal("0");
		tiposPago.setTipopagoid(1);

		bnBanco = false;
		bnEfectivo = false;
		bnTarjeta = false;
	}

	public void calcularDescuentoDolares() {
//		Map<String, Object> parametro = egresoService
//				.calcularDescuentoDolares(facturaReporte);
//		facturaReporte = (FacturaReporte) parametro.get("fr");
//		presentaMensaje((FacesMessage) parametro.get("mensaje"));
	}

	public void calcularDescuentoPorcentaje() {
//		Map<String, Object> parametro = egresoService
//				.calcularDescuentoPorcentaje(facturaReporte);
//		facturaReporte = (FacturaReporte) parametro.get("fr");
//		presentaMensaje((FacesMessage) parametro.get("mensaje"));
	}

	public void calcularEntrada() {
		EntradaReporte entradaReporte = new EntradaReporte();
		if (entrada.getFechapago() != null) {
			pagosEntrada.setCuota(entrada.getCuota());
			pagosEntrada.setTipopago(tiposPago);
			pagosEntrada.setFechapago(timestamp(entrada.getFechapago()));
			pagosEntrada.setPagado(true);
			entrada.setPagado(true);
			entrada.setSaldo(new BigDecimal("0"));
			entrada.setFechamora(fechaFormatoDate("01-01-1900"));
			entradaReporte.setFechaPago(entrada.getFechapago());
			entradaReporte.setPagado(true);
			entrada.addPagoentrada(pagosEntrada);
			egreso.addEntrada(entrada);
		} else if (tiposPago.getTipopagoid() == 3) {
			entrada.setPagado(false);
			entrada.setSaldo(entrada.getCuota());
			entrada.setFechamora(fechaFormatoDate("01-01-1900"));
			pagosEntrada.setCuota(entrada.getCuota());
			pagosEntrada.setTipopago(tiposPago);
			pagosEntrada.setFechapago(timestamp("01-01-1900"));
			pagosEntrada.setPagado(false);
			entrada.addPagoentrada(pagosEntrada);
			egreso.addEntrada(entrada);
			entradaReporte.setPagado(false);
		} else {
			entrada.setPagado(false);
			entrada.setSaldo(entrada.getCuota());
			Calendar c = new GregorianCalendar();
			c.setTime(fechaInicio);
			c.add(Calendar.DATE, 15);
			entrada.setFechamora(c.getTime());
			entradaReporte.setPagado(false);
			egreso.addEntrada(entrada);
		}
		entradaReporte.setFecha(entrada.getFechalimite());
		entradaReporte.setCuota(entrada.getCuota());

		if (tiposPago.getTipopagoid() != 0)
			entradaReporte.setTipoPago(tipoPagoService.obtenerPorTipoPagoId(
					tiposPago.getTipopagoid()).getNombre());

		BigDecimal tm = new BigDecimal("0");
		List<Entrada> list = egreso.getEntradas();
		for (Entrada e : list)
			tm = tm.add(e.getCuota());

		totalMonto = tm;
		restante = restanteAux = cantidadFacturaCalculos.getTotal().subtract(
				totalMonto);
		if (totalMonto.compareTo(cantidadFacturaCalculos.getTotal()) > 0)
			cambio = totalMonto.subtract(cantidadFacturaCalculos.getTotal());

		listaEntradaReporte.add(entradaReporte);

		tiposPago = new Tipopago();
		bnBanco = false;
		bnEfectivo = false;
		bnTarjeta = false;
		tiposPago.setTipopagoid(1);

	}

	public void calcularPrecioCantidad() {
//		facturaReporte = egresoService.calcularPrecioCantidad(facturaReporte);
	}

	public void calcularPrecioPromocion() {
//		facturaReporte = egresoService.calcularPrecioPromocion(facturaReporte,
//				producto.getIva());
	}

	public void calcularPrecioSubTotal() {
//		Map<String, Object> parametro = egresoService
//				.calcularDescuentoPorcentaje(facturaReporte);
//		facturaReporte = (FacturaReporte) parametro.get("fr");
//		FacesMessage fm = (FacesMessage) parametro.get("mensaje");
//		if (fm != null)
//			presentaMensaje(fm);
	}

	public void calcularPrecioTotal() {
//		facturaReporte = egresoService.calcularPrecioTotal(facturaReporte);
	}

	public void calcularPrecioUnit() {
//		facturaReporte = egresoService.calcularPrecioUnit(facturaReporte);
	}

	public void cambiarCantidad() {
//		FacturaReporte f = facturaReportes.get(fila);
//		int can = kardexService.obtenerSaldoActual(f.getCodigo(),
//				bodega.getBodegaid()).getCantidad();
//
//		if (cantidad > can || cantidad <= 0)
//			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
//					"ERROR", "INGRESE UNA CANTIDAD MENOR A LA EXISTENTE: "
//							+ can + " O MAYOR QUE CERO"));
//		else if (cantidad != f.getCantidad())
//			facturaReportes.set(fila, egresoService.recalcular(fila, f,
//					egreso.getDetalleegresos(), cantidadFacturaCalculos,
//					cantidad, null, true));
//
//		cantidad = null;
//		fila = null;
	}

	public void cambiarDescuento() {
//		Map<String, Object> parametro = egresoService.cambiarDescuentoFactura(
//				cantidadFacturaCalculos, cantidadFacturaPresentar);
//		cantidadFacturaCalculos = (CantidadFactura) parametro.get("cfc");
//		cantidadFacturaPresentar = (CantidadFactura) parametro.get("cfp");
//		egreso.setDescuento(cantidadFacturaCalculos.getDescuentoEgreso());
//		presentaMensaje((FacesMessage) parametro.get("mensaje"));
	}

	public void cambiarPrecio() {
//		FacturaReporte f = facturaReportes.get(fila);
//
//		BigDecimal precio = productoService.obtenerPorProductoId(
//				f.getProductoId()).getPrecio();
//		if (nuevoPrecio.compareTo(precio) < 0)
//			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
//					"ERROR", "EL PRECIO NO DEBE SER MENOR AL PRECIO DE COSTO: "
//							+ precio));
//		else if (nuevoPrecio != f.getPrecioUnitVenta())
//			facturaReportes.set(fila, egresoService.recalcular(fila, f,
//					egreso.getDetalleegresos(), cantidadFacturaCalculos, null,
//					nuevoPrecio, true));
//
//		nuevoPrecio = null;
//		fila = null;
	}

	public void cancelar() {
		facturaReporte = new FacturaReporte();
	}

	public void cancelarEntrada() {
		entrada = new Entrada();
		pagosEntrada = new Pagoentrada();
		tiposPago = new Tipopago();
		setBnEfectivo(true);
		setBnTarjeta(false);
		setBnBanco(false);
		tiposPago.setTipopagoid(1);
	}

	public void cancelarPago() {
		listaEntradaReporte = new ArrayList<EntradaReporte>();
		egreso.setEntradas(new ArrayList<Entrada>());
		cambio = newBigDecimal();
		restante = cantidadFacturaCalculos.getTotal();
		cancelarEntrada();
	}

	public void cancelarTodo() {
		bn = true;
		xxx();
		cliente = new Persona();
		entrada = new Entrada();
		pagosEntrada = new Pagoentrada();
		fechaInicio = new Date();
		listaEntradaReporte = new ArrayList<EntradaReporte>();
		facturaReportes = new ArrayList<FacturaReporte>();
		cantidadFacturaCalculos = new CantidadFactura();
		restante = newBigDecimal();
		cambio = newBigDecimal();
	}

	public void cargarCliente(SelectEvent event) {
		cliente = clienteService.obtenerPorPersonaId(cliente.getPersonaid());
		egreso.setCliente(cliente.getCliente());
	}

	public void cargarProducto(SelectEvent event) {
		producto = productoService.obtenerPorProductoId(producto
				.getProductoid());
		facturaReporte.setProductoId(producto.getProductoid());
		Integer precioId = productoService.obtenerPvpPorProducto(producto
				.getTipoPrecioProductos());
		if (precioId == null) {
			precioId = producto.getTipoPrecioProductos().get(0)
					.getTipoprecioproductoid();
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
					"MENSAJE DEL SISTEMA",
					"EL PRODUCTO NO TIENE CONFIGURADO EL PVP"));
		}

		facturaReporte.setPrecioId(precioId);

		obtenerPrecio();
	}

	public boolean comprobarCabecera() {
		RequestContext context = RequestContext.getCurrentInstance();
		boolean error = false;
		if (guia) {
			if (guiaRemision.getMotivotraslado().getMotivotrasladoid() == 0) {
				error = true;
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"MENSAJE DEL SISTEMA",
						"ERROR: INGRESE UN MOTIVO DE TRNASLADO"));
			} else if (guiaRemision.getPlaca().compareTo("") == 0) {
				error = true;
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"MENSAJE DEL SISTEMA", "ERROR: INGRESE UNA PLACA"));
			} else if (transportista.getEmpleadocargoid() == 0) {
				error = true;
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"MENSAJE DEL SISTEMA",
						"ERROR: INGRESE UN TRANSPORTISTA"));
			}

		}
		if (cliente.getCliente() == null) {
			error = true;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "INGRESE UN CLIENTE"));
			System.out.println("entre en cliente");
		} else if (egreso.getLocal().getLocalid() == null) {
			error = true;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "ESCOJA UN LOCAL"));
			System.out.println("entre en local");
		} else if (egreso.getCodigodocumento() == null) {
			error = true;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "INGRESE UN CODIGO DE DOCUMENTO"));
			System.out.println("entre en documento");
		} else if (vendedor.getEmpleadocargoid() == 0) {
			error = true;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "ESCOJA UN VENDEDOR"));
		} else if (egreso.getDetalleegresos().size() <= 0) {
			error = true;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "INGRESE PRODUCTOS"));
		}
		System.out.println(error);
		if (error) {
			context.addCallbackParam("error5", true);
			return true;
		} else {
			context.addCallbackParam("error5", false);
			return false;
		}
	}

	public boolean comprobarCantidadFinal() {
		boolean bn = true;

		List<Detalleegreso> detalleEgreso = egresoService
				.duplicarDetalleEgreso(egreso.getDetalleegresos());

		List<Detalleegreso> detalleEgresoFinal = egresoService
				.sumarCantidades(detalleEgreso);
		for (Detalleegreso de : detalleEgresoFinal) {

			Producto producto = productoService.obtenerPorProductoId(de
					.getProducto().getProductoid());

			int cantidad = kardexService.obtenerSaldoActual(producto.getEan(),
					bodega.getBodegaid()).getCantidad();

			if (de.getCantidad() > cantidad) {
				bn = false;
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"ERROR", "LA SUMA DE LAS CANTIDADES DEL PRODUCTO: "
								+ producto.getEan() + " ES MAYOR A: "
								+ cantidad));
			}
		}

		return bn;
	}

	public boolean comprobarDetalleEgreso() {
		RequestContext context = RequestContext.getCurrentInstance();
		boolean bn = true;

		if (egreso.getDetalleegresos().isEmpty()) {
			bn = false;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR", "DEBE INGRESAR DETALLES"));
		}

		if (bn)
			context.addCallbackParam("error", true);
		else
			context.addCallbackParam("error", false);

		return bn;
	}

	public void comprobarGuiaRemision() {
		String mensaje = guia ? "LA FACTURA TENDRA GUIA DE REMISION"
				: "LA FACTURA NO TENDRA GUIA DE REMISION";
		presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
				"MENSAJE DEL SISTEMA", "AVISO: " + mensaje));
	}

	public void comprobarLocal() {
		RequestContext context = RequestContext.getCurrentInstance();
		boolean bn = true;
		if (egreso.getLocal().getLocalid() == null
				|| egreso.getLocal().getLocalid() == 0) {
			bn = false;
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR", "DEBE ESCOJER UN LOCAL"));
		} else {
			Local local = localService.obtenerPorLocalId(egreso.getLocal()
					.getLocalid());
			if (local.getBodegalocals() == null
					&& local.getBodegalocals().isEmpty()) {
				bn = false;
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"ERROR",
						"EL LOCAL QUE ESCOJIO NO TIENE BODEGAS ASOCIADAS"));
			}
		}

		if (bn)
			context.addCallbackParam("error1", true);
		else
			context.addCallbackParam("error1", false);
	}

	public void comprobarPrecioCosto() {
		BigDecimal precio = productoService.obtenerPorProductoId(
				facturaReporte.getProductoId()).getPrecio();
		if (facturaReporte.getPrecioUnitVenta().compareTo(precio) < 0)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"ERROR", "EL PRECIO NO DEBE SER MENOR AL PRECIO DE COSTO: "
							+ precio));
		else {
			if (facturaReporte.getCantidad() != null)
				facturaReporte = egresoService.calcularTotales(facturaReporte);

			if (facturaReporte.getIva().compareToIgnoreCase("I") == 0)
				facturaReporte.setPrecioUnitIva(iva(facturaReporte
						.getPrecioUnitVenta()));
			else
				facturaReporte.setPrecioUnitIva(newBigDecimal());

			facturaReporte.setPrecioUnitTotal(redondear(facturaReporte
					.getPrecioUnitVenta()
					.add(facturaReporte.getPrecioUnitIva())));
		}
	}

	public void convertirFactura(Egreso e) {
		cancelarTodo();
		this.egreso = egresoService.obtenerPorEgresoId(e.getEgresoid());
		cliente = e.getCliente().getPersona();
		obtenerBodega();
		List<Detalleegreso> list = egreso.getDetalleegresos();
		for (Detalleegreso detalleEgreso : list) {
			FacturaReporte fr = egresoService.asignar(detalleEgreso, null,
					egreso.getTipodocumento().getTipodocumentoid());
			cantidadFacturaCalculos = egresoService.calcularCantidadFactura(
					cantidadFacturaCalculos, fr, "add");
			facturaReportes.add(fr);
		}
	}

	public void eliminarDetalle(ActionEvent actionEvent) {
		int posicion = egresoService.posicion(facturaReporte,
				egreso.getDetalleegresos(), true);
		if (posicion >= 0) {
			Detalleegreso de = egreso.getDetalleegresos().get(posicion);
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
					"ELIMINÓ DETALLE", "Elimino: " + de.getProducto().getEan()));
			egreso.removeDetalleegreso(de);
			cantidadFacturaCalculos = egresoService.calcularCantidadFactura(
					cantidadFacturaCalculos, facturaReporte, "subtract");
			restante = restanteAux = cantidadFacturaCalculos.getTotal();
			facturaReportes.remove(facturaReporte);
			cancelar();
		}
	}

	public BigDecimal getCambio() {
		return cambio;
	}

	public Integer getCantidad() {
		return cantidad;
	}

	public CantidadFactura getCantidadFacturaCalculos() {
		return cantidadFacturaCalculos;
	}

	public CantidadFactura getCantidadFacturaPresentar() {
		return egresoService.redondearCantidadFactura(cantidadFacturaPresentar,
				cantidadFacturaCalculos);
	}

	public String getChequeTarjetaCuenta() {
		return chequeTarjetaCuenta;
	}

	public String getChequeTarjetaVaucher() {
		return chequeTarjetaVaucher;
	}

	public Persona getCliente() {
		return cliente;
	}

	public String getCriterioClienteBusqueda() {
		return criterioClienteBusqueda;
	}

	public String getCriterioProductoBusqueda() {
		return criterioProductoBusqueda;
	}

	public Egreso getEgreso() {
		return egreso;
	}

	public Entrada getEntrada() {
		if (entrada.getPagoentradas() == null)
			entrada.setPagoentradas(new ArrayList<Pagoentrada>());
		return entrada;
	}

	public FacturaReporte getFacturaReporte() {
		return facturaReporte;
	}

	public List<FacturaReporte> getFacturaReportes() {
		return facturaReportes;
	}

	public Date getFechaInicio() {
		return fechaInicio;
	}

	public Guiaremision getGuiaRemision() {
		return guiaRemision;
	}

	public List<Persona> getListaClienteBusqueda() {
		return listaClienteBusqueda;
	}

	public List<EntradaReporte> getListaEntradaReporte() {
		return listaEntradaReporte;
	}

	public List<Local> getListaLocales() {
		return listaLocales;
	}

	public List<Motivotraslado> getListaMotivotraslados() {
		return listaMotivotraslados;
	}

	public List<Producto> getListaProductoBusqueda() {
		return listaProductoBusqueda;
	}

	public List<PersonaCedulaNombre> getListaTransportistas() {
		return listaTransportistas;
	}

	public List<PersonaCedulaNombre> getListaVendedores() {
		return listaVendedores;
	}

	public List<Tipopago> getListTiposPago() {
		listTiposPago = tipoPagoService.obtener();
		return listTiposPago;
	}

	public BigDecimal getNuevoPrecio() {
		return nuevoPrecio;
	}

	public Pagoentrada getPagosEntrada() {
		return pagosEntrada;
	}

	public Producto getProducto() {
		return producto;
	}

	public BigDecimal getRestante() {
		return restante;
	}

	public BigDecimal getRestanteAux() {
		return restanteAux;
	}

	public Tipopago getTiposPago() {
		return tiposPago;
	}

	public BigDecimal getTotalMonto() {
		return totalMonto;
	}

	public Empleadocargo getTransportista() {
		return transportista;
	}

	public Empleadocargo getVendedor() {
		return vendedor;
	}

	public void imprimirFactura() {
		List<FacturaReporte> list = new ArrayList<FacturaReporte>();
		for (int i = 0; i < egreso.getDetalleegresos().size(); i++)
			list.add(egresoService.asignar(egreso.getDetalleegresos().get(i),
					facturaReportes.get(i), 1));

		egresoReport.reporteFactura(egreso,
				clienteService.obtenerPorPersonaId(cliente.getPersonaid()),
				cantidadFacturaCalculos, list);
		cancelarTodo();
	}

	@PostConstruct
	public void init() {
		setListaLocales(localService.obtenerPorCajero(SecurityContextHolder
				.getContext().getAuthentication().getName()));

		listaVendedores = empleadoService.obtenerPorCargo(5);
		listaTransportistas = empleadoService.obtenerPorCargo(6);
		listaMotivotraslados = motivoTrasladoService.obtener(true);
		xxx();
		tiposPago.setTipopagoid(1);
	}

	public void insertarDetalle(ActionEvent actionEvent) {
		if (producto == null)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "ESCOJA UN PRODUCTO"));
		else {
			producto = productoService.obtenerPorProductoId(producto
					.getProductoid());

			Kardex kardex = kardexService.obtenerSaldoActual(producto.getEan(),
					bodega.getBodegaid());

			if (facturaReporte.getPrecioUnitVenta().compareTo(
					kardex.getPrecio()) < 0) {
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"ERROR",
						"EL PRECIO NO DEBE SER MENOR AL PRECIO DE COSTO"));
			} else if (facturaReporte.getCantidad() <= kardex.getCantidad()
					&& facturaReporte.getCantidad() > 0) {
				Detalleegreso detalleEgreso = new Detalleegreso();

				detalleEgreso.setProducto(producto);

				facturaReporte = egresoService.asignar(detalleEgreso,
						facturaReporte, 0);

				detalleEgreso.setCantidad(facturaReporte.getCantidad());
				detalleEgreso.setPreciocosto(kardex.getPrecio());
				detalleEgreso.setPrecioventa(facturaReporte
						.getPrecioUnitVenta());
				detalleEgreso
						.setDescuento(facturaReporte.getDescuentoDolares());

				detalleEgreso.setIva(producto.getIva());
				detalleEgreso.setPromocion(facturaReporte.isPromocion());
				detalleEgreso.setEliminar(facturaReporte.isEliminar());

				cantidadFacturaCalculos = egresoService
						.calcularCantidadFactura(cantidadFacturaCalculos,
								facturaReporte, "add");

				facturaReportes.add(facturaReporte);
				egreso.addDetalleegreso(detalleEgreso);

				restante = restanteAux = cantidadFacturaCalculos.getTotal();
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
						"INSERTÓ DETALLE", "INSERTO: " + producto.getEan()));
				limpiarObjetosBusquedaProductos();
				bnLocal = true;
			} else
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"ERROR", "INGRESE UNA CANTIDAD MENOR A LA EXISTENTE: "
								+ kardex.getCantidad() + " O MAYOR QUE CERO"));
		}
	}

	public void insertarOrActualizar(ActionEvent actionEvent) {
		if (!comprobarCabecera() && comprobarCantidadFinal()
				&& comprobarDetalleEgreso()) {
			bn = false;

			boolean pagado = true;

			List<Entrada> list = egreso.getEntradas();
			if (list.isEmpty())
				pagado = false;
			for (Entrada e : list)
				if (e.getPagado() == false
						|| e.getCuota().compareTo(
								cantidadFacturaCalculos.getTotal()) < 0)
					pagado = false;

			egreso.setPagado(pagado);

			if (egreso.getEgresoid() == null) {
				egreso.setVendedorid(vendedor);
				egresoService.insertar(egreso, bodega);
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
						"INSERTÓ", "Egreso: " + egreso.getCodigodocumento()));
			} else if (egreso.getTipodocumento().getTipodocumentoid() != 1) {
				egreso.setVendedorid(vendedor);
				egresoService.insertar(egresoService.duplicarEgreso(egreso, 1),
						bodega);
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
						"INSERTÓ", "Egreso: " + egreso.getCodigodocumento()));
			} else {
				egresoService.actualizar(egreso, bodega);
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
						"ACTUALIZO", "Egreso: " + egreso.getCodigodocumento()));
				cancelarTodo();
			}

			if (guia == true
					&& guiaRemision.getMotivotraslado().getMotivotrasladoid() != 0
					&& transportista.getEmpleadocargoid() != 0
					&& guiaRemision.getPlaca() != null) {

				guiaRemision.setCliente(cliente.getCliente());
				guiaRemision.setRazonsocialdestinatario(cliente.getCliente()
						.getNombrecomercial());
				guiaRemision.setTransportistaid(empleadoService
						.obtenerPorEmpleadoCargoId(transportista
								.getEmpleadocargoid()));
				guiaRemision.setFechainicio(new Date());
				guiaRemision.setFechaterminacion(new Date());
				guiaRemision.setPuntollegada(cliente.getCiudad().getNombre());
				String ciudad = localService.obtenerPorLocalId(
						egreso.getLocal().getLocalid()).getCiudad();
				guiaRemision.setPuntopartida(ciudad);

				guiaRemision.setEgresos(new ArrayList<Egreso>());
				guiaRemision.addEgreso(egreso);

				guiaRemision.setMotivotraslado(motivoTrasladoService
						.obtenerPorMotivoTrasladoId(guiaRemision
								.getMotivotraslado().getMotivotrasladoid()));
//				guiaRemisionService.insertar(guiaRemision);
			}
		}
	}

	public boolean isBn() {
		return bn;
	}

	public boolean isBnBanco() {
		return bnBanco;
	}

	public boolean isBnEfectivo() {
		return bnEfectivo;
	}

	public boolean isBnLocal() {
		return bnLocal;
	}

	public boolean isBnTarjeta() {
		return bnTarjeta;
	}

	public boolean isGuia() {
		return guia;
	}

	public void limpiarObjetosBusquedaCliente() {
		criterioClienteBusqueda = new String();
		listaClienteBusqueda = new ArrayList<Persona>();
	}

	public void limpiarObjetosBusquedaProductos() {
		criterioProductoBusqueda = new String();
		// listaProductoBusqueda = new ArrayList<Producto>();
		producto = new Producto();
		facturaReporte = new FacturaReporte();
	}

	public void obtenerBodega() {
		Local local = localService.obtenerPorLocalId(egreso.getLocal()
				.getLocalid());
		if (local.getBodegalocals() != null
				&& !local.getBodegalocals().isEmpty())
			bodega = local.getBodegalocals().get(0).getBodega();
	}

	public void obtenerClientesPorBusqueda() {
		if (criterioClienteBusqueda.length() >= 0
				&& criterioClienteBusqueda.length() <= 3) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "INGRESE MAS DE 3 CARACTERES"));
		} else {
			listaClienteBusqueda = clienteService
					.obtener(criterioClienteBusqueda.toUpperCase());
			if (listaClienteBusqueda.isEmpty()) {
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
						"MENSAJE DEL SISTEMA",
						"NO SE ENCONTRO NINGUNA COINCIDENCIA"));
			}
			criterioClienteBusqueda = new String();
		}
	}

	public void obtenerFila(CellEditEvent event) {
		fila = event.getRowIndex();
	}

	public void obtenerPrecio() {
		facturaReporte.setPrecioUnitVenta(productoService.calcularPrecio(
				producto, bodega.getBodegaid(), facturaReporte.getPrecioId()));

		facturaReporte.setIva(facturaReporte.isPromocion() ? "" : producto
				.getIva() ? "I" : "");

		if (facturaReporte.getCantidad() != null)
			facturaReporte = egresoService.calcularTotales(facturaReporte);

		facturaReporte.setPrecioUnitIva(facturaReporte.getIva()
				.compareToIgnoreCase("I") == 0 ? iva(facturaReporte
				.getPrecioUnitVenta()) : newBigDecimal());

		facturaReporte.setPrecioUnitTotal(redondear(facturaReporte
				.getPrecioUnitVenta().add(facturaReporte.getPrecioUnitIva())));
	}

	public void obtenerProductosPorBusqueda() {
		if (criterioProductoBusqueda.length() >= 0
				&& criterioProductoBusqueda.length() <= 3)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "INGRESE MAS DE 3 CARACTERES"));
		else {
			listaProductoBusqueda = productoService.obtenerPorLocal(
					criterioProductoBusqueda.toUpperCase(), egreso.getLocal()
							.getLocalid());
			if (listaProductoBusqueda.isEmpty())
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"MENSAJE DEL SISTEMA",
						"NO SE ENCONTRO NINGUN RESULTADO"));
			criterioProductoBusqueda = new String();
		}
	}

	private void presentaMensaje(FacesMessage message) {
		FacesContext.getCurrentInstance().addMessage(null, message);
	}

	public void setBn(boolean bn) {
		this.bn = bn;
	}

	public void setBnBanco(boolean bnBanco) {
		this.bnBanco = bnBanco;
	}

	public void setBnEfectivo(boolean bnEfectivo) {
		this.bnEfectivo = bnEfectivo;
	}

	public void setBnLocal(boolean bnLocal) {
		this.bnLocal = bnLocal;
	}

	public void setBnTarjeta(boolean bnTarjeta) {
		this.bnTarjeta = bnTarjeta;
	}

	public void setCambio(BigDecimal cambio) {
		this.cambio = cambio;
	}

	public void setCantidad(Integer cantidad) {
		this.cantidad = cantidad;
	}

	public void setCantidadFacturaCalculos(
			CantidadFactura cantidadFacturaCalculos) {
		this.cantidadFacturaCalculos = cantidadFacturaCalculos;
	}

	public void setCantidadFacturaPresentar(
			CantidadFactura cantidadFacturaPresentar) {
		this.cantidadFacturaPresentar = cantidadFacturaPresentar;
	}

	public void setChequeTarjetaCuenta(String chequeTarjetaCuenta) {
		this.chequeTarjetaCuenta = chequeTarjetaCuenta;
	}

	public void setChequeTarjetaVaucher(String chequeTarjetaVaucher) {
		this.chequeTarjetaVaucher = chequeTarjetaVaucher;
	}

	public void setCliente(Persona cliente) {
		this.cliente = cliente;
	}

	public void setCriterioClienteBusqueda(String criterioClienteBusqueda) {
		this.criterioClienteBusqueda = criterioClienteBusqueda;
	}

	public void setCriterioProductoBusqueda(String criterioProductoBusqueda) {
		this.criterioProductoBusqueda = criterioProductoBusqueda;
	}

	public void setEgreso(Egreso egreso) {
		this.egreso = egreso;
	}

	public void setEntrada(Entrada entrada) {
		this.entrada = entrada;
	}

	public void setFacturaReporte(FacturaReporte facturaReporte) {
		this.facturaReporte = facturaReporte;
	}

	public void setFacturaReportes(List<FacturaReporte> facturaReportes) {
		this.facturaReportes = facturaReportes;
	}

	public void setFechaInicio(Date fechaInicio) {
		this.fechaInicio = fechaInicio;
	}

	public void setGuia(boolean guia) {
		this.guia = guia;
	}

	public void setGuiaRemision(Guiaremision guiaRemision) {
		this.guiaRemision = guiaRemision;
	}

	public void setListaClienteBusqueda(List<Persona> listaClienteBusqueda) {
		this.listaClienteBusqueda = listaClienteBusqueda;
	}

	public void setListaEntradaReporte(List<EntradaReporte> listaEntradaReporte) {
		this.listaEntradaReporte = listaEntradaReporte;
	}

	public void setListaLocales(List<Local> listaLocales) {
		this.listaLocales = listaLocales;
	}

	public void setListaMotivotraslados(
			List<Motivotraslado> listaMotivotraslados) {
		this.listaMotivotraslados = listaMotivotraslados;
	}

	public void setListaProductoBusqueda(List<Producto> listaProductoBusqueda) {
		this.listaProductoBusqueda = listaProductoBusqueda;
	}

	public void setListaTransportistas(
			List<PersonaCedulaNombre> listaTransportistas) {
		this.listaTransportistas = listaTransportistas;
	}

	public void setListaVendedores(List<PersonaCedulaNombre> listaVendedores) {
		this.listaVendedores = listaVendedores;
	}

	public void setListTiposPago(List<Tipopago> listTiposPago) {
		this.listTiposPago = listTiposPago;
	}

	public void setNuevoPrecio(BigDecimal nuevoPrecio) {
		this.nuevoPrecio = nuevoPrecio;
	}

	public void setPagosEntrada(Pagoentrada pagosEntrada) {
		this.pagosEntrada = pagosEntrada;
	}

	public void setProducto(Producto producto) {
		this.producto = producto;
	}

	public void setRestante(BigDecimal restante) {
		this.restante = restante;
	}

	public void setRestanteAux(BigDecimal restanteAux) {
		this.restanteAux = restanteAux;
	}

	public void setTiposPago(Tipopago tiposPago) {
		this.tiposPago = tiposPago;
	}

	public void setTotalMonto(BigDecimal totalMonto) {
		this.totalMonto = totalMonto;
	}

	public void setTransportista(Empleadocargo transportista) {
		this.transportista = transportista;
	}

	public void setVendedor(Empleadocargo vendedor) {
		this.vendedor = vendedor;
	}

	public void tipoPago() {
		if (tiposPago.getTipopagoid() == 1) {
			setBnEfectivo(true);
			setBnTarjeta(false);
			setBnBanco(false);
		} else if (tiposPago.getTipopagoid() == 2) {
			setBnEfectivo(false);
			setBnTarjeta(true);
			setBnBanco(false);
			setChequeTarjetaCuenta("# TARJETA");
			setChequeTarjetaVaucher("# VAUCHER");
		} else if (tiposPago.getTipopagoid() == 3) {
			setBnEfectivo(false);
			setBnTarjeta(true);
			setBnBanco(true);
			setChequeTarjetaCuenta("# CUENTA");
			setChequeTarjetaVaucher("# CHEQUE");
		}
	}

	private void xxx() {
		bnLocal = false;
		egreso = new Egreso();
		guiaRemision = new Guiaremision();
		guiaRemision.setMotivotraslado(new Motivotraslado());
		egreso.setLocal(new Local());
		vendedor = new Empleadocargo();
		transportista = new Empleadocargo();

		egreso.setEntradas(new ArrayList<Entrada>());
		egreso.setDetalleegresos(new ArrayList<Detalleegreso>());
		egreso.setTipodocumento(tipoDocumentoService.obtenerPorId(1));

		egreso.setCodigodocumento(parametro
				.getCodigoestablecimiento()
				.concat("-")
				.concat(parametro
						.getCodigoemision()
						.concat("-")
						.concat(String.format("%09d",
								parametro.getSecuenciafactura() + 1))));

		if (listaLocales.size() == 1) {
			egreso.setLocal(listaLocales.get(0));
			obtenerBodega();
			setBnLocal(true);
		}
	}

}